﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using Toolkit.Web.Infastructure;

namespace Toolkit.Web.ViewComponents.DataGrid
{
    public interface IReadOnlyDataGridColumnFilter
    {
        string Key
        {
            get;
        }

        DataGridColumnFilterType Type
        {
            get;
        }

        DataExpression FieldExpression
        {
            get;
        }

        Type FieldValueType
        {
            get;
        }

        IList<DataGridFilterOperator> AvailableOperators
        {
            get;
        }

        DataGridFilterOperator AppliedOperator
        {
            get;
        }

        IDictionary<string, string> AvailableValues
        {
            get;
        }

        IList<string> AppliedValues
        {
            get;
        }

        bool IsFilterApplied();
    }

    public class DataGridColumnFilter : IReadOnlyDataGridColumnFilter
    {
        private IDictionary<string, string> _availableValues;
        private HtmlTemplate<DataGridColumnFilter> _customFilterTemplate;

        public DataGridColumnFilter(string key, DataGridColumnFilterType filterType, string expression, Type valueType)
        {
            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentException("key");
            }

            if (string.IsNullOrEmpty(expression))
            {
                throw new ArgumentException("expression");
            }

            if (valueType.GetInterface(typeof(IComparable).FullName) == null)
            {
                throw new ArgumentException("type");
            }

            Key = key;
            Type = filterType;
            FieldExpression = new DataExpression(expression);
            FieldValueType = valueType;
            AvailableOperators = GetRecommendedOperators(Type);
            HtmlAttributes = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
        }

        public IDictionary<string, object> HtmlAttributes
        {
            get;
            private set;
        }

        public string Key
        {
            get;
            set;
        }

        public DataGridColumnFilterType Type
        {
            get;
            private set;
        }

        public DataExpression FieldExpression
        {
            get;
            private set;
        }

        public Type FieldValueType
        {
            get;
            private set;
        }

        public IList<DataGridFilterOperator> AvailableOperators
        {
            get;
            set;
        }

        public DataGridFilterOperator AppliedOperator
        {
            get;
            set;
        }

        public IDictionary<string, string> AvailableValues
        {
            get
            {
                if (Type != DataGridColumnFilterType.SingleSelect && Type != DataGridColumnFilterType.MultiSelect && Type != DataGridColumnFilterType.Custom)
                {
                    throw new NotSupportedException();
                }
                return _availableValues;
            }
            set
            {
                if (Type != DataGridColumnFilterType.SingleSelect && Type != DataGridColumnFilterType.MultiSelect && Type != DataGridColumnFilterType.Custom)
                {
                    throw new NotSupportedException();
                }
                _availableValues = value;
            }
        }

        public IList<string> AppliedValues
        {
            get;
            set;
        }

        public HtmlTemplate<DataGridColumnFilter> CustomFilterTemplate
        {
            get
            {
                if (Type != DataGridColumnFilterType.Custom)
                {
                    throw new NotSupportedException();
                }
                return _customFilterTemplate;
            }
            set
            {
                if (Type != DataGridColumnFilterType.Custom)
                {
                    throw new NotSupportedException();
                }
                _customFilterTemplate = value;
            }
        }

        public IList<DataGridFilterOperator> GetRecommendedOperators(DataGridColumnFilterType type)
        {
            IList<DataGridFilterOperator> operators = new List<DataGridFilterOperator>();
            operators.Add(DataGridFilterOperator.None);

            if (type == DataGridColumnFilterType.Search)
            {
                operators.Add(DataGridFilterOperator.Contains);
                operators.Add(DataGridFilterOperator.DoesNotContain);
                operators.Add(DataGridFilterOperator.StartsWith);
                operators.Add(DataGridFilterOperator.EndsWith);
                operators.Add(DataGridFilterOperator.IsEqualTo);
                operators.Add(DataGridFilterOperator.IsNotEqualTo);
                operators.Add(DataGridFilterOperator.IsEmptyOrNull);
                operators.Add(DataGridFilterOperator.IsNotEmptyOrNull);
            }
            else if (type == DataGridColumnFilterType.SingleSelect)
            {
                operators.Add(DataGridFilterOperator.IsEqualTo);
                operators.Add(DataGridFilterOperator.IsNotEqualTo);
            }
            else if (type == DataGridColumnFilterType.MultiSelect)
            {
                operators.Add(DataGridFilterOperator.IsContainedIn);
                operators.Add(DataGridFilterOperator.IsNotContainedIn);
            }
            else if (type == DataGridColumnFilterType.Compare)
            {
                operators.Add(DataGridFilterOperator.IsLessThan);
                operators.Add(DataGridFilterOperator.IsLessThanOrEqualTo);
                operators.Add(DataGridFilterOperator.IsGreaterThan);
                operators.Add(DataGridFilterOperator.IsGreaterThanOrEqualTo);
            }

            return operators;
        }

        public bool IsFilterApplied()
        {
            return (
                AppliedOperator != DataGridFilterOperator.None &&
                (
                    (AppliedValues != null && AppliedValues.Count > 0) ||
                    (AppliedOperator == DataGridFilterOperator.IsEmptyOrNull || AppliedOperator == DataGridFilterOperator.IsNotEmptyOrNull)
                )
            );
        }
    }
}
